import { resetRouter } from '@/router/index'
import { getAuths, handleAsyncRoutes } from "@/router/utils";
import { isEmpty, isIncludeAllChildren, isString, storageLocal } from "@pureadmin/utils";
import { message } from './message';
import dayjs from 'dayjs'
import { PLATFORM_Map, usePageVariablesStoreHook } from '@/store/modules/pageVariables';
import { userKey } from './auth';
/**
 * 日期时间格式化
 */
export const timeFormats = {
  d: "YYYY-MM-DD",
  dt: "YYYY-MM-DD HH:mm:ss",
  y: "YYYY",
  ym: "YYYY-MM",
  ymc: "YYYY年MM月",
  md: "MM-DD",
  hm: "HH:mm"
}

/** 动态路由加载，router中配置路由+传入路由 */
export const addDynamicRoute = (route: any | any[]) => {
  // 清除缓存
  storageLocal().removeItem("async-routes");
  // 重置并加载本地路由
  resetRouter()
  // 加载接口返回路由
  handleAsyncRoutes(Array.isArray(route) ? route : [route])
  // 缓存路由
  storageLocal().setItem("async-routes", route);
}
/**
 *
 * @param fn 请求方法
 * @param timeout 请求间隔
 * @param immediate 是否立即执行
 * @returns (params) => void params: 传递给请求方法的请求参数
 */
export const customDebounce = (fn: (params?: any) => void, timeout = 200, immediate = false) => {
  let timer = null
  return (...params: any[]) => {
    if (!immediate) {
      clearTimeout(timer)
      timer = setTimeout(() => {
        fn(...params)
      }, timeout)
    } else {
      if (!timer) {
        timer = setTimeout(() => {
          clearTimeout(timer)
          timer = null
        }, timeout)
        fn(...params)
      }
    }
  }
}
// 从路径中获取文件名
export const getFileNameFromPath = path => {
  // 使用字符串分割函数获取路径中的文件名
  const pathParts = path.split("?")[0].split("/");
  return pathParts[pathParts.length - 1];
};
/**
 *
 * @param fn 请求方法
 * @param timeout 请求间隔
 * @param immediate 是否立即执行
 * @returns (...params: any[]) => Promise<any> 传递给请求方法的请求参数
 */
export const customPromiseDebounce = (fn: Function, timeout = 200, immediate = false): (...params: any[]) => Promise<any> => {
  let timer = null
  let loding = false
  return (...params: any[]): Promise<any> =>
    new Promise((resolve, reject) => {
      if (!immediate && !loding) {
        clearTimeout(timer)
        loding = true
        timer = setTimeout(() => {
          fn(...params).then(res => {
            resolve(res)
          }).catch(rej => {
            reject(rej)
          }).finally(() => {
            loding = false
          })
        }, timeout)
      } else {
        // timeout时间内只能请求一次且上一次请求已经完成
        if (!timer && !loding) {
          loding = true
          timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null
          }, timeout)
          fn(...params).then(res => {
            resolve(res)
          }).catch(rej => {
            reject(rej)
          }).finally(() => {
            loding = false
          })
        } else if (loding) {
          message('请求中...', { type: 'warning' })
          reject('请求中')
        } else {
          message('请勿重复请求', { type: 'warning' })
          reject('请勿重复请求')
        }
      }
    })
}

//缩略图
export const thumbImg = url => {
  // return url + '?imageMogr2/auto-orient/thumbnail/!25p/blur/1x0/quality/75'
  return url + "?imageView2/0/format/webp/q/75";
};

/**
 * 动态方法 若多个方法满足条件则返回最后一个满足条件的
 * @param judg 判断数组，格式为 [{ bool: 判断条件, fun: 返回方法 }]
 * @param elseFun 默认返回方法
 * @returns 返回方法
 */
export const dynamicFunction = (judg?: { bool: boolean, fun: Function }[], elseFun?: Function) => {
  if (!elseFun) elseFun = () => { }
  let resFun = elseFun
  judg?.forEach(item => {
    if (item.bool) {
      resFun = item.fun
    }
  })
  return resFun
}
/**
 * 获取图片信息
 * @param img 图片对象获取链接
 * @returns Promise<{ width: number, height: number }>
 */
export const getImageInfo = (img: HTMLImageElement | string): Promise<{ width: number, height: number }> => {
  return new Promise((resolve, reject) => {
    let resImg = null
    if (typeof img === 'string') {
      resImg = new Image()
      resImg.src = img
    } else {
      resImg = img
    }
    resImg.onload = () => {
      resolve({
        width: resImg.width,
        height: resImg.height
      })
    }
    resImg.onerror = () => {
      reject(new Error('图片加载失败'))
    }
  })
}
/**
 * 获取项目静态资源路径
 * @param url 资源路径
 * @returns 资源链接
 */
export const getAssetURL = (url) => {
  return new URL(url, import.meta.url).href
}
/**
 * 数组求和
 * @param arr 数组
 * @param parseField 求和参数 类型为字符串或函数 默认为数组元素本身
 * @returns 求和结果
 */
export const arrSum = (arr: any, parseField: any = (item) => item) => {
  parseField = commonNormalization(parseField)
  var s = 0;
  arr.forEach((val) => {
    s += parseField(val);
  });
  return s;
}


/**
 * 数组去重与查重
 * @param arr 检测数组
 * @param checkFun 检测方法 类型为字符串（属性名称）或函数 默认为元素本身,函数返回值为检测属性不可为对象
 * @param unique true 去重 false 查重
 */
export const arrayUniqueAndRepeat = (arr: any, checkFun: any = (item, index?, arr?) => item, unique = false) => {
  checkFun = commonNormalization(checkFun)
  const res = new Map();
  if (unique) {
    return arr?.filter((item, index, arr) => !res.has(checkFun(item, index, arr)) && res.set(checkFun(item, index, arr), 1));
  } else {
    return arr?.some((item: any) => !(!res.has(checkFun(item)) && res.set(checkFun(item), 1)));
  }
}
/**
* 通用参数归一化方法模板
* @param parameter 归一化参数 类型为字符串或函数 支持字符串格式为"key"或"key.key"
* @returns 归一化后的函数
*/
export const commonNormalization = (parameter) => {
  if (typeof parameter === 'function') {
    return parameter
  } else if (typeof parameter === 'string') {
    if (parameter.indexOf('.') !== -1) {
      const arr = parameter.split('.')
      return (item: any) => {
        let res = item
        arr.forEach(item => {
          res = res[item]
        })
        return res
      }
    } else {
      return (item: any) => item[parameter]
    }
  } else {
    console.error('参数类型错误');
  }
}
/**
 * element-plus 表单字段校验方法
 * @param formRef 表单对象
 * @param fieldId 字段id
 */
export const formValidateField = (formRef, fieldId) => {
  formRef.validateField(fieldId)
}


/**
 * 时间格式化
 * @param str 时间 string | "" | null
 * @param type 格式 timeFormats中 ： "d" | 'dt' | "y" | "ym" | "ymc" | 'md' | 'hm'
 *
 * d: "YYYY-MM-DD",
 * dt: "YYYY-MM-DD HH:mm:ss",
 * y: "YYYY",
 * ym: "YYYY-MM",
 * ymc: "YYYY年MM月",
 * md: "MM-DD",
 * hm: "HH:mm"
 */
export const timeFormat = (str, type) => {

  let layout = timeFormats[type] ?? ""
  return dayjs(str).format(layout)

}

export const isDisabled = (unityId) => {
  // return usePageVariablesStoreHook().getManage().unityId != Number(unityId)
  return false
}

function getUserAuths(): Array<string> {
  let userAuths = [''];
  if (usePageVariablesStoreHook().getPlatform() == PLATFORM_Map.manage) {
    userAuths = storageLocal().getItem(userKey)?.userInfo?.roles?.manage
  } else if (usePageVariablesStoreHook().getPlatform() == PLATFORM_Map.operate) {
    userAuths = storageLocal().getItem(userKey)?.userInfo?.roles?.operate
  }
  return userAuths as Array<string>;
}
export const haveRole = (value) => {
  const userAuths = getUserAuths();
  if (userAuths?.length == 0) return true;
  if (!value) return false;
  /** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
  const metaAuths = getAuths();
  // if (!metaAuths) return false;
  // const isMetaAuths = isString(value)
  //   ? metaAuths.includes(value)
  //   : isIncludeAllChildren(value, metaAuths);
  const isUserAuths = isString(value)
    ? userAuths.includes(value)
    : isIncludeAllChildren(value, metaAuths);
  // return isMetaAuths && isUserAuths ? true : false;
  return isUserAuths;
}

/**
 * 判断字段是否为null或者为""返回"--"
 */
export const isNullOrEmpty = (val: any, defaultVal:any = '--') => {
  val = val?.toString()
  return (val && !isEmpty(val)) ? val : defaultVal
}
/** 初始化puretable表格配置 */
export const initPureTableConfig = (config: any[]) => {
  config.forEach(item => {
    if (item?.prop) {
      item.formatter = (val) => isNullOrEmpty(val[item.prop])
    }
  })
  return config
}

/**
 * 修改网站Favicon
 * @param newIconPath Favicon 地址
 */
export function changeFavicon(newIconPath: string) {
  if (!newIconPath) {
    return false;
  }
  let link = {
    href: '',
  };;
  link = document.querySelector('link[rel="icon"]');
  if (link && link.href) {
    link.href = newIconPath;
  } else {
    const newLink = document.createElement('link');
    newLink.rel = 'icon';
    newLink.href = newIconPath;
    document.head.appendChild(newLink);
  }
}
